﻿using System;
using System.Linq;
using KSPCapability;
using UnityEngine;

public interface IWarpGUI
{
	void Render();
	void FixedUpdate();
}

public class BaseGUI : IWarpGUI
{
	private readonly CapabilityBooster _capabilityBooster;

	public BaseGUI(CapabilityBooster capabilityBooster)
	{
		_capabilityBooster = capabilityBooster;
	}

	private bool doit = false;
	
	public void Render()
	{
		GUILayout.Label("Select base:");

		if (GUILayout.Button("Test"))
		{
			doit = true;
		}

	}

	public void FixedUpdate()
	{
		if (doit)
		{
			
  //public Vector3d getTruePositionAtUT(double UT)
  //{
  //  return this.getRelativePositionAtUT(UT).xzy + this.referenceBody.getTruePositionAtUT(UT);
  //}

			if (FlightGlobals.ActiveVessel.Landed)
				FlightGlobals.ActiveVessel.Landed = false;
			if (FlightGlobals.ActiveVessel.Splashed)
				FlightGlobals.ActiveVessel.Splashed = false;

			FlightGlobals.ActiveVessel.GoOnRails();

			var universalTime = Planetarium.GetUniversalTime();

			var currentPos = FlightGlobals.ActiveVessel.orbit.getTruePositionAtUT(Planetarium.GetUniversalTime());

			var body = FlightGlobals.Bodies.First<CelestialBody>(b => b.GetName() == "Kerbin");

			var lat = 62.680808;
			var lon = 45.741960;

			var alt = body.pqsController.GetSurfaceHeight(
					QuaternionD.AngleAxis(lon, Vector3d.down) *
					QuaternionD.AngleAxis(lat, Vector3d.forward) * Vector3d.right) -
						  body.pqsController.radius;
			alt = Math.Max(alt, 0); // Underwater!

			var pos = body.GetWorldSurfacePosition(lat, lon, alt + 100);

			var wantedTruePos = (pos.xzy + body.getTruePositionAtUT(universalTime));
			var diff = wantedTruePos - currentPos;
			MonoBehaviour.print("Diff: " + diff.magnitude);
			//CapabilityBooster.Krakensbane.setOffset(diff);

			//FlightGlobals.ActiveVessel.SetReferenceTransform(body.GetTransform());
			FlightGlobals.ActiveVessel.SetPosition(pos, true);
			FlightGlobals.ActiveVessel.SetWorldVelocity(new Vector3d(0,0,0));

			Krakensbane.ResetVelocityFrame();

			doit = false;

			FlightGlobals.ActiveVessel.Landed = true;

			FlightGlobals.ActiveVessel.GoOffRails();

			if (FlightGlobals.ActiveVessel.Landed)
				FlightGlobals.ActiveVessel.Landed = true;
		}
	}
}

public class OrbitGUI : IWarpGUI
{
	private CapabilityBooster _capabilityBooster;
	protected string selectedBody = null;
	protected float selectedAltitude = 0;
	protected float selectedLAN = 0;
	protected float selectedInc = 0;

	protected Orbit _selectedOrbit;

	public OrbitGUI(CapabilityBooster capabilityBooster)
	{
		_capabilityBooster = capabilityBooster;
	}

	public void Render()
	{
		if (_capabilityBooster.AvaliableOptions.Any())
		{
			GUILayout.Label("Select orbit:");

			if (selectedBody == null)
			{
				foreach (var capability in _capabilityBooster.AvaliableOptions)
				{
					if (GUILayout.Button(capability.Body))
					{
						selectedBody = capability.Body;
						selectedAltitude = (float) capability.Min.Altitude;
						selectedInc = (float) ((capability.Min.Inclination + capability.Max.Inclination)/2f);
						selectedLAN = (float) ((capability.Min.LAN + capability.Max.LAN)/2f);
					}
				}
			}
			else
			{
				var range = _capabilityBooster.AvaliableOptions.Single(r => r.Body == selectedBody);

				GUILayout.Label("Altitude:");
				selectedAltitude = GUILayout.HorizontalSlider(selectedAltitude, (float) range.Min.Altitude,
				                                              (float) range.Max.Altitude);

				GUILayout.Label("Inclination:");
				selectedInc = GUILayout.HorizontalSlider(selectedInc, (float) range.Min.Inclination, (float) range.Max.Inclination);

				GUILayout.Label("LAN:");
				selectedLAN = GUILayout.HorizontalSlider(selectedLAN, (float) range.Min.LAN, (float) range.Max.LAN);

				if (
					GUILayout.Button(string.Format("Boost to {0}: {1:0}km Inc:{2:0.0} LAN:{3:0.0}", selectedBody,
					                               selectedAltitude/1000.0,
					                               selectedInc, selectedLAN)))
				{
					_selectedOrbit =
						new Capability {Body = selectedBody, Altitude = selectedAltitude, Inclination = selectedInc, LAN = selectedLAN}
							.ToOrbit();
				}

				if (GUILayout.Button("< Back"))
				{
					selectedBody = null;
				}
			}
		}
		else
		{
			GUILayout.Label("No suitable orbits");
		}
	}

	public void FixedUpdate()
	{
		if (_selectedOrbit != null)
		{
			if (FlightGlobals.ActiveVessel.Landed)
				FlightGlobals.ActiveVessel.Landed = false;
			if (FlightGlobals.ActiveVessel.Splashed)
				FlightGlobals.ActiveVessel.Splashed = false;

			foreach (var part in FlightGlobals.ActiveVessel.parts.ToArray().Where(part => part.Modules.OfType<LaunchClamp>().Any())) part.Die();

			_selectedOrbit.UpdateFromUT(Planetarium.GetUniversalTime());
			FlightGlobals.ActiveVessel.GoOnRails();

			var diff = _selectedOrbit.getTruePositionAtUT(Planetarium.GetUniversalTime()) - FlightGlobals.ActiveVessel.orbit.getTruePositionAtUT(Planetarium.GetUniversalTime());

			CapabilityBooster.Krakensbane.setOffset(diff);

			FlightGlobals.ActiveVessel.SetPosition(_selectedOrbit.getPositionAtUT(Planetarium.GetUniversalTime()));

			_selectedOrbit.UpdateFromUT(Planetarium.GetUniversalTime());

			FlightGlobals.ActiveVessel.orbit.UpdateFromOrbitAtUT(_selectedOrbit, Planetarium.GetUniversalTime(), _selectedOrbit.referenceBody);

			FlightGlobals.ActiveVessel.GoOffRails();

			_selectedOrbit = null;

			_capabilityBooster.explode();
		}
	}
}